package com.ht.api.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ht.api.business.ad.PlanHelper;
import com.ht.api.db.*;
import com.ht.api.db.task.HtTaskExecutor;
import com.ht.api.db.task.TaskHandler;
import com.ht.api.db.util.HtUtil;
import com.ht.api.task.ad.CreatePlanTask;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class EventService {


    /**
     * 批量检查用户事件
     * @param tenantId
     */
    public static void batchCheckEvent (long tenantId) {
        DataSource ds = DbConfig.useTenantDb(tenantId);
        StreamLoadConfig config = DbConfig.useTenantSLC(tenantId);

        DbList eventList = Db.createSqlParser("user_event_log").query(ds);

        Mapper.translate(ds, eventList);

        String time = DateUtil.now();

        for (Entity event : eventList) {
            if (!event.getMainId().equals("1909176311910371328")) {
               continue;
            }
            String openid = event.getStr("openid");
            String oneid = event.getByPath("mapper_openid.oneid", String.class);

            String relationId = event.getStr("relation_id");
            String eventType = event.getStr("event_type");
            String eventKey = event.getStr("event_key");

            long count = Db.createSqlParser("event_trigger_user_log").where("openid", openid)
                    .where("event_key", eventKey).where("event_type", eventType).where("relation_id", relationId).count(ds);

            if (count > 0) {
                continue;
            }

            List<Entity> dataList = new ArrayList<>();

            Entity eventTriggerUserLog = Entity.create("event_trigger_user_log");
            eventTriggerUserLog.set("openid", openid);
            eventTriggerUserLog.set("event_type", eventType);
            eventTriggerUserLog.set("event_key", eventKey);
            eventTriggerUserLog.set("relation_id", relationId);
            eventTriggerUserLog.set("event_time", time);

            Db.insert(ds, eventTriggerUserLog);

            doContext(dataList, event);

            // 检查效果配置
            checkEffectConfig (ds, dataList, openid, relationId, eventType, eventKey, time);
            checkEffectConfig (ds, dataList, openid, null, eventType, eventKey, time);

            // 检查运营任务配置
            checkOpsTaskConfig (ds, dataList, oneid, relationId, eventType, eventKey, time);
            checkOpsTaskConfig (ds, dataList, oneid, null, eventType, eventKey, time);

            // 检查广告配置
            checkAdConfig (tenantId, ds, dataList, oneid, relationId, eventType, eventKey, time);
            checkAdConfig (tenantId, ds, dataList, oneid, null, eventType, eventKey, time);

            DbList tagList = Db.createSqlParser("tag_relation").where("relation_id", relationId).query(ds);
            for (Entity tag : tagList) {
                String tagId = tag.getStr("tag_id");

                checkEffectConfig (ds, dataList, openid, tagId, eventType, eventKey, time);
                checkOpsTaskConfig (ds, dataList, oneid, tagId, eventType, eventKey, time);
                checkAdConfig (tenantId, ds, dataList, oneid, tagId, eventType, eventKey, time);
            }

            Db.insertBatchWithStream(config, dataList);
        }

    }

    public static void doContext (List<Entity> dataList, JSONObject event) {
        String eventType = event.getStr("event_type");
        String eventKey = event.getStr("event_key");

        JSONObject context = event.getJSONObject("context");

        for (String idType : context.keySet()) {
            String id = context.getStr(idType);

            Entity eventRelationCount = Entity.create("event_relation_count");
            eventRelationCount.set("event_type", eventType);
            eventRelationCount.set("event_key", eventKey);
            eventRelationCount.set("relation_id", id);
            eventRelationCount.set("num", 1);

            switch (idType) {
                case "openid":
                    eventRelationCount.set("relation_type", 6);
                    break;
                case "ad_id":
                    eventRelationCount.set("relation_type", 1);
                    break;
                case "userid":
                    eventRelationCount.set("relation_type", 3);
                    break;
                case "chat_id":
                    eventRelationCount.set("relation_type", 4);
                    break;
                case "plan_id":
                    eventRelationCount.set("relation_type", 8);
                    break;
                case "creative_id":
                    eventRelationCount.set("relation_type", 7);
                    break;
            }

            dataList.add(eventRelationCount);
        }

    }


    /**
     * 检查广告配置
     * @param tenantId
     * @param ds
     * @param oneid
     * @param relationId
     * @param eventType
     * @param eventkey
     * @param time
     */
    public static void checkAdConfig (long tenantId, DataSource ds, List<Entity> dataList, String oneid, String relationId, String eventType, String eventkey, String time) {


        DbList eventAdConfigList = DbList.create();

        if (StrUtil.isNotBlank(relationId)) {
            eventAdConfigList = Db.createSqlParser("event_ad_config").where("relation_id", relationId).where("status", 1).query(ds);

        } else {
            String configId = HtUtil.uniqueStrToNum(eventType + eventkey);
            Entity eventAdConfig = Db.createSqlParser("event_ad_config").where("main_id", configId).findOne(ds);

            if (eventAdConfig != null) {
                eventAdConfigList.add(eventAdConfig);
            }
        }

        for (Entity adConfig : eventAdConfigList) {
            String configId = adConfig.getMainId();

            String audienceSql = "select bitmap_union(to_bitmap(oneid)) oneid from audience_relation where oneid = "+oneid+" and status = 0 and audience_id in (" + adConfig.getJSONArray("audience_rule").join(",") + ") ";

            StringBuilder appSql = PlanHelper.buildAppSql(adConfig.getJSONObject("app_rule"));

            StringBuilder checkSql = new StringBuilder();
            if (StrUtil.isNotBlank(audienceSql) && appSql != null) {
                checkSql.append("select bitmap_count(bitmap_and(t1.oneid, t2.oneid)) num from ").append("("+audienceSql+") t1, ").append("("+appSql.toString()+") t2 ");
            } else if (StrUtil.isBlank(audienceSql) && appSql != null) {
                checkSql.append("select bitmap_count(t.oneid) num from ").append("("+appSql.toString()+") t ");
            } else if (StrUtil.isNotBlank(audienceSql) && appSql == null) {
                checkSql.append("select bitmap_count(t.oneid) num from ").append("("+audienceSql+") t ");
            }

            if (checkSql.length() > 0) {
                int count = Db.val(ds, checkSql.toString(), Integer.class);
                if (count == 0) {
                    continue;
                }
            }

            DbList adPlanConfigList = Db.createSqlParser("event_ad_plan_config").where("config_id", configId)
                    .where("event_type", eventType).where("event_key", eventkey).where("status", 1).query(ds);

            for (Entity adPlanConfig : adPlanConfigList) {
                String planId = adPlanConfig.getStr("plan_id");
                String campaignId = adPlanConfig.getStr("campaign_id");
                Entity plan = Db.createSqlParser("ad_plan").where("main_id", planId).findOne(ds);

                Entity planUser = Entity.create("ad_plan_user");
                planUser.set("oneid", oneid);
                planUser.set("source_id", plan.get("source_id"));
                planUser.set("source_type", plan.get("source_type"));
                planUser.set("plan_id", planId);
                planUser.set("first_in_time", time);
                planUser.set("last_in_time", time);
                planUser.set("push_days", 1);
                planUser.set("status", 1);

                dataList.add(planUser);

                Entity adPlanUserLogs = Entity.create("ad_plan_user_logs");
                adPlanUserLogs.set("oneid", oneid);
                adPlanUserLogs.set("plan_id", planId);
                adPlanUserLogs.set("time", time);
                adPlanUserLogs.set("status", 1);

                dataList.add(adPlanUserLogs);

                DbList campaignItemList = Db.createSqlParser("ad_campaign_item").where("campaign_id", campaignId).query(ds);
                for (Entity campaignItem : campaignItemList) {
                    Entity creative = PlanHelper.findCreativeByCampaignItem(ds, campaignItem, oneid);

                    if (creative == null) { // 没有创意，则不用创建广告任务
                        continue;
                    }

                    Entity touchUser = PlanHelper.findTouchUser(tenantId, oneid, campaignItem.getStr("ad_position"), adConfig.getJSONObject("app_rule"));
                    Entity userAdTask = PlanHelper.buildAdTaskToUser(plan, touchUser, campaignItem, creative);
                    dataList.add(userAdTask);
                }

            }

        }

        log.info("checkAdConfig dataList " + dataList.size());
    }


    /**
     * 检查运营任务配置
     * @param ds
     * @param oneid
     * @param relationId
     * @param eventType
     * @param eventKey
     * @param time
     */
    public static void checkOpsTaskConfig (DataSource ds, List<Entity> dataList, String oneid, String relationId, String eventType, String eventKey, String time) {
        SqlParser parser = Db.createSqlParser("event_ops_task_config").where("event_key", eventKey).where("event_type", eventType);

        if (StrUtil.isNotBlank(relationId)) {
            parser.where("relation_id", relationId);
        } else {
            parser.where("relation_id", "is", null);
        }

        DbList opsTaskConfigList = parser.query(ds);

        // 需要判断运营任务得分是否已满足吗？
        for (Entity opsTaskConfig : opsTaskConfigList) {
            String taskId = opsTaskConfig.getStr("task_id");

            long count = Db.createSqlParser("ops_tasks_users").where("status", 0).where("oneid", oneid).where("task_id", taskId).count(ds);

            if (count == 0) {
                continue;
            }

            int score = opsTaskConfig.getInt("score");

            Entity opsTasksUsersSorceLogs = Entity.create("ops_tasks_users_sorce_logs");
            opsTasksUsersSorceLogs.set("oneid", oneid);
            opsTasksUsersSorceLogs.set("task_id", taskId);
            opsTasksUsersSorceLogs.set("time", time);
            opsTasksUsersSorceLogs.set("score", score);
            opsTasksUsersSorceLogs.set("msg", "");

            dataList.add(opsTasksUsersSorceLogs);
        }

//        log.info("checkOpsTaskConfig dataList " + dataList.size());
    }


    /**
     * 检查效果配置
     * @param ds
     * @param openid
     * @param relationId
     * @param eventType
     * @param eventKey
     * @param time
     */
    public static void checkEffectConfig (DataSource ds, List<Entity> dataList, String openid, String relationId, String eventType, String eventKey, String time) {
        boolean isCheckEffectConfig = true;

        Entity eventLimitConfig = Db.createSqlParser("sys_event_limit_config").where("event_type", eventType).where("event_key", eventKey).findOne();
        if (eventLimitConfig != null) {
            JSONObject limitConfig = eventLimitConfig.getJSONObject("limit_config");
            Integer day = limitConfig.getInt("day");
            Integer week = limitConfig.getInt("week");
            Integer month = limitConfig.getInt("month");
            Integer forever = limitConfig.getInt("forever");

            String countSql = """
                        SELECT
                            COUNT(CASE WHEN DATE(event_time) = DATE(':input_time') THEN 1 ELSE 0 END) AS daily_count,
                            COUNT(CASE WHEN YEARWEEK(event_time, 1) = YEARWEEK(':input_time', 1) THEN 1 ELSE 0 END) AS weekly_count,
                            COUNT(CASE WHEN YEAR(event_time) = YEAR(':input_time') AND MONTH(event_time) = MONTH(':input_time') THEN 1 ELSE 0 END) AS monthly_count,
                            SUM(sys_deleted) AS total_count
                        FROM
                            event_trigger_user_log
                        """;

            countSql = countSql.replaceAll(":input_time", DateUtil.now());
            countSql += "WHERE openid in ('" + openid + "')";

            Entity eventCount = Db.findOne(ds, countSql);
            if (day != null && eventCount.getInt("daily_count") >= day) {
                isCheckEffectConfig = false;
            }
            if (week != null && eventCount.getInt("weekly_count") >= week) {
                isCheckEffectConfig = false;
            }
            if (month != null && eventCount.getInt("monthly_count") >= month) {
                isCheckEffectConfig = false;
            }
            if (forever != null && eventCount.getInt("total_count") >= forever) {
                isCheckEffectConfig = false;
            }

        }

        Entity effectConfig = Db.createSqlParser("event_effect_config")
                .where("main_id", HtUtil.uniqueStrToNum(relationId + eventKey + eventType)).findOne(ds);

        if (isCheckEffectConfig && effectConfig != null) {
            int points = effectConfig.getInt("points");
            if (points > 0) {
                Entity userPointsLogs = Entity.create("user_points_logs");
                userPointsLogs.getMainId();
                userPointsLogs.set("openid", openid);
                userPointsLogs.set("points", points);
                userPointsLogs.set("time", time);
                userPointsLogs.set("msg", "");
                userPointsLogs.set("type", 1);

                dataList.add(userPointsLogs);
            }

            int growthValue = effectConfig.getInt("growth_value");
            if (growthValue > 0) {
                Entity userGrowthValueLogs = Entity.create("user_growth_value_logs");
                userGrowthValueLogs.set("openid", openid);
                userGrowthValueLogs.set("growth_value", growthValue);
                userGrowthValueLogs.set("time", time);
                userGrowthValueLogs.set("msg", "");
                userGrowthValueLogs.set("type", 1);

                dataList.add(userGrowthValueLogs);
            }

            int aliveValue = effectConfig.getInt("alive_value");
            if (aliveValue > 0) {
                Entity userAliveValueLogs = Entity.create("user_alive_value_logs");
                userAliveValueLogs.set("openid", openid);
                userAliveValueLogs.set("alive_value", aliveValue);
                userAliveValueLogs.set("time", time);
                userAliveValueLogs.set("msg", "");

                dataList.add(userAliveValueLogs);
            }
        }

//        log.info("checkEffectConfig dataList " + dataList.size());

    }


    public static void formatRelation (DataSource ds, Entity entity) {
        String relationId = entity.getStr("relation_id");
        String relationType = entity.getStr("relation_type");

        Entity relation = Db.createSqlParser(relationType).where("main_id", relationId).findOne(ds);
        if (relationType.equals("ad")) {
            entity.set("ad", JSONUtil.createObj().set("name", relation.getStr("name")));
        } else if (relationType.equals("wx_workuser")) {
            JSONObject workuser = JSONUtil.createObj();
            workuser.set("alias", relation.get("alias"));
            workuser.set("avatar", relation.get("avatar"));
            workuser.set("name", relation.get("name"));
            workuser.set("userid", relation.get("userid"));
            workuser.set("tenant_appid", relation.get("tenant_appid"));

            entity.set("workuser", workuser);
        } else if (relationType.equals("wx_groupchat")) {
            JSONObject groupchat = JSONUtil.createObj();
            groupchat.set("avatar", relation.get("avatar"));
            groupchat.set("name", relation.get("name"));
            groupchat.set("chat_id", relation.get("chat_id"));
            groupchat.set("tenant_appid", relation.get("tenant_appid"));

            entity.set("groupchat", groupchat);
        } else if (relationType.equals("product")) {
            JSONObject product = JSONUtil.createObj();
            product.set("product_id", relation.get("product_id"));
            product.set("name", relation.get("name"));
            product.set("main_image", relation.get("main_image"));
            product.set("appid", relation.get("appid"));

            entity.set("product", product);
        }

    }

    public static void formatEventMsg (Entity event) {
        String eventType = event.getStr("event_type");
        String eventKey = event.getStr("event_key");

        String relationId = event.getStr("relation_id");
        String relationType = event.getStr("relation_id");


    }

    public static String getRelationName (DataSource ds, String relationType, String relationId) {
        String name = "";



        return null;
    }




}
